home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.0 / stk-3 / blt-for-STk-3.0 / blt-1.9 / src / bltGrHairs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-01  |  13.2 KB  |  449 lines

  1.  
  2. /*
  3.  * bltGrHairs.c --
  4.  *
  5.  *    This module implements a crosshairs for the graph widget.
  6.  *
  7.  * Copyright 1991-1994 by AT&T Bell Laboratories.
  8.  * Permission to use, copy, modify, and distribute this software
  9.  * and its documentation for any purpose and without fee is hereby
  10.  * granted, provided that the above copyright notice appear in all
  11.  * copies and that both that the copyright notice and warranty
  12.  * disclaimer appear in supporting documentation, and that the
  13.  * names of AT&T Bell Laboratories any of their entities not be used
  14.  * in advertising or publicity pertaining to distribution of the
  15.  * software without specific, written prior permission.
  16.  *
  17.  * AT&T disclaims all warranties with regard to this software, including
  18.  * all implied warranties of merchantability and fitness.  In no event
  19.  * shall AT&T be liable for any special, indirect or consequential
  20.  * damages or any damages whatsoever resulting from loss of use, data
  21.  * or profits, whether in an action of contract, negligence or other
  22.  * tortuous action, arising out of or in connection with the use or
  23.  * performance of this software.
  24.  *
  25.  * Graph widget created by Sani Nassif and George Howlett.
  26.  */
  27.  
  28. #include "blt.h"
  29. #include "bltGraph.h"
  30.  
  31.  
  32. extern Tk_CustomOption bltPositionOption;
  33.  
  34. /*
  35.  * -------------------------------------------------------------------
  36.  *
  37.  * Crosshairs
  38.  *
  39.  *    Contains the line segments positions and graphics context used
  40.  *    to simulate crosshairs (by XORing) on the graph.
  41.  *
  42.  * -------------------------------------------------------------------
  43.  */
  44. typedef struct {
  45.     CrosshairsToggleProc *toggleProc;
  46.     CrosshairsUpdateProc *updateProc;
  47.     CrosshairsConfigProc *configProc;
  48.     CrosshairsDestroyProc *destroyProc;
  49.  
  50.     XPoint anchorPos;        /* Hot spot for crosshairs */
  51.     int state;            /* Internal state of crosshairs. If non-zero,
  52.                  * crosshairs are displayed. */
  53.     int mapped;            /* Requested state of crosshairs (on/off). This
  54.                  * is not necessarily consistent with the
  55.                  * internal state variable.  This is true when
  56.                  * the hot spot is off the graph.  */
  57.     int dashes;            /* Dashstyle of the crosshairs. This represents
  58.                  * the number of alternatingly drawn pixels. If
  59.                  * zero, the hairs are drawn as a solid line */
  60.     int lineWidth;        /* Width of the simulated crosshair lines */
  61.     XSegment segArr[2];        /* Positions of line segments representing the
  62.                  * simulated crosshairs. */
  63.     XColor *colorPtr;        /* Foreground color of crosshairs */
  64.     GC gc;            /* Graphics context for crosshairs. Set to
  65.                  * GXxor to not require redraws of graph */
  66. } Crosshairs;
  67.  
  68. #define DEF_HAIRS_DASHES    "0"
  69. #define DEF_HAIRS_FG_COLOR    BLACK
  70. #define DEF_HAIRS_FG_MONO    BLACK
  71. #define DEF_HAIRS_LINE_WIDTH    "0"
  72. #define DEF_HAIRS_MAPPED    "0"
  73. #define DEF_HAIRS_POSITION    (char *)NULL
  74.  
  75. static Tk_ConfigSpec configSpecs[] =
  76. {
  77.     {TK_CONFIG_COLOR, "-color", "color", "Color",
  78.     DEF_HAIRS_FG_COLOR, Tk_Offset(Crosshairs, colorPtr),
  79.     TK_CONFIG_COLOR_ONLY},
  80.     {TK_CONFIG_INT, "-dashes", "xhairsDashes", "Dashes",
  81.     DEF_HAIRS_DASHES, Tk_Offset(Crosshairs, dashes), 0},
  82.     {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
  83.     DEF_HAIRS_FG_MONO, Tk_Offset(Crosshairs, colorPtr),
  84.     TK_CONFIG_MONO_ONLY},
  85.     {TK_CONFIG_INT, "-linewidth", "xhairsLineWidth", "XhairsLinewidth",
  86.     DEF_HAIRS_LINE_WIDTH, Tk_Offset(Crosshairs, lineWidth),
  87.     TK_CONFIG_DONT_SET_DEFAULT},
  88.     {TK_CONFIG_BOOLEAN, "-mapped", "xhairsMapped", "XhairsMapped",
  89.     DEF_HAIRS_MAPPED, Tk_Offset(Crosshairs, mapped),
  90.     TK_CONFIG_DONT_SET_DEFAULT},
  91.     {TK_CONFIG_CUSTOM, "-position", "xhairsPosition", "XhairsPosition",
  92.     DEF_HAIRS_POSITION, Tk_Offset(Crosshairs, anchorPos),
  93.     0, &bltPositionOption},
  94.     {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
  95. };
  96.  
  97. extern int Blt_PointOnGraph _ANSI_ARGS_((Graph *, XPoint *));
  98.  
  99. /*
  100.  *----------------------------------------------------------------------
  101.  *
  102.  * TurnOffHairs --
  103.  *
  104.  *    XOR's the existing line segments (representing the crosshairs),
  105.  *    thereby erasing them.  The internal state of the crosshairs is
  106.  *    tracked.
  107.  *
  108.  * Results:
  109.  *    None
  110.  *
  111.  * Side Effects:
  112.  *    Crosshairs are erased.
  113.  *
  114.  *----------------------------------------------------------------------
  115.  */
  116. static void
  117. TurnOffHairs(tkwin, hairsPtr)
  118.     Tk_Window tkwin;
  119.     Crosshairs *hairsPtr;
  120. {
  121.     if (Tk_IsMapped(tkwin) && (hairsPtr->state)) {
  122.     XDrawSegments(Tk_Display(tkwin), Tk_WindowId(tkwin), hairsPtr->gc,
  123.         hairsPtr->segArr, 2);
  124.     hairsPtr->state = 0;
  125.     }
  126. }
  127.  
  128. /*
  129.  *----------------------------------------------------------------------
  130.  *
  131.  * TurnOnHairs --
  132.  *
  133.  *    Draws (by XORing) new line segments, creating the effect of
  134.  *    crosshairs. The internal state of the crosshairs is tracked.
  135.  *
  136.  * Results:
  137.  *    None
  138.  *
  139.  * Side Effects:
  140.  *    Crosshairs are displayed.
  141.  *
  142.  *----------------------------------------------------------------------
  143.  */
  144. static void
  145. TurnOnHairs(tkwin, hairsPtr)
  146.     Tk_Window tkwin;
  147.     Crosshairs *hairsPtr;
  148. {
  149.     if (Tk_IsMapped(tkwin) && (!hairsPtr->state)) {
  150.     XDrawSegments(Tk_Display(tkwin), Tk_WindowId(tkwin), hairsPtr->gc,
  151.         hairsPtr->segArr, 2);
  152.     hairsPtr->state = 1;
  153.     }
  154. }
  155.  
  156. /*
  157.  *----------------------------------------------------------------------
  158.  *
  159.  * ConfigureCrosshairs --
  160.  *
  161.  *    Configures attributes of the crosshairs such as line width,
  162.  *    dashes, and position.  The crosshairs are first turned off
  163.  *    before any of the attributes changes.
  164.  *
  165.  * Results:
  166.  *    None
  167.  *
  168.  * Side Effects:
  169.  *    Crosshair GC is allocated.
  170.  *
  171.  *----------------------------------------------------------------------
  172.  */
  173. static void
  174. ConfigureCrosshairs(graphPtr)
  175.     Graph *graphPtr;
  176. {
  177.     XGCValues gcValues;
  178.     unsigned long gcMask;
  179.     GC newGC;
  180.     long colorValue;
  181.     Crosshairs *hairsPtr = (Crosshairs *)graphPtr->crosshairs;
  182.  
  183.     /*
  184.      * Turn off the crosshairs temporarily. This is in case the new
  185.      * configuration changes the size, style, or position of the lines.
  186.      */
  187.     TurnOffHairs(graphPtr->tkwin, hairsPtr);
  188.  
  189.     gcValues.function = GXxor;
  190.  
  191.     /* The graph's color option may not have been set yet */
  192.     if (graphPtr->plotBg == NULL) {
  193.     colorValue = WhitePixelOfScreen(Tk_Screen(graphPtr->tkwin));
  194.     } else {
  195.     colorValue = graphPtr->plotBg->pixel;
  196.     }
  197.     gcValues.background = colorValue;
  198.     gcValues.foreground = (colorValue ^ hairsPtr->colorPtr->pixel);
  199.  
  200.     if (hairsPtr->lineWidth < 0) {
  201.     hairsPtr->lineWidth = 0;
  202.     }
  203.     gcValues.line_width = hairsPtr->lineWidth;
  204.     gcMask = (GCForeground | GCBackground | GCFunction | GCLineWidth);
  205.     if (hairsPtr->dashes > 0) {
  206.     gcValues.dashes = hairsPtr->dashes;
  207.     gcValues.dash_offset = 0;
  208.     gcValues.line_style = LineOnOffDash;
  209.     gcMask |= (GCDashOffset | GCDashList | GCLineStyle);
  210.     }
  211.     newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
  212.     if (hairsPtr->gc != NULL) {
  213.     Tk_FreeGC(graphPtr->display, hairsPtr->gc);
  214.     }
  215.     hairsPtr->gc = newGC;
  216.  
  217.     /*
  218.      * Are the new coordinates on the graph?
  219.      */
  220.     if (!Blt_PointOnGraph(graphPtr, &(hairsPtr->anchorPos))) {
  221.     return;            /* Coordinates are off the graph */
  222.     }
  223.     hairsPtr->segArr[0].x2 = hairsPtr->segArr[0].x1 = hairsPtr->anchorPos.x;
  224.     hairsPtr->segArr[0].y1 = graphPtr->origin.y;
  225.     hairsPtr->segArr[0].y2 = graphPtr->extreme.y;
  226.     hairsPtr->segArr[1].y2 = hairsPtr->segArr[1].y1 = hairsPtr->anchorPos.y;
  227.     hairsPtr->segArr[1].x1 = graphPtr->origin.x;
  228.     hairsPtr->segArr[1].x2 = graphPtr->extreme.x;
  229.  
  230.     if (hairsPtr->mapped) {
  231.     TurnOnHairs(graphPtr->tkwin, hairsPtr);
  232.     }
  233. }
  234.  
  235. /*
  236.  *----------------------------------------------------------------------
  237.  *
  238.  * ToggleCrosshairs --
  239.  *
  240.  *    Turn on or off crosshair simulation if it has been requested
  241.  *    and the current crosshair position is in the plotting area.
  242.  *    This routine is used to erase the crosshairs before the
  243.  *    graph is redrawn (invalidating the XOR'ed old crosshairs).
  244.  *
  245.  * Results:
  246.  *    The return value is a standard Tcl result.
  247.  *
  248.  * Side Effects:
  249.  *    Crosshairs may be drawn or erased from the plotting area.
  250.  *
  251.  *----------------------------------------------------------------------
  252.  */
  253. static void
  254. ToggleCrosshairs(graphPtr)
  255.     Graph *graphPtr;
  256. {
  257.     Crosshairs *hairsPtr = (Crosshairs *)graphPtr->crosshairs;
  258.  
  259.     if ((hairsPtr->mapped) && (hairsPtr->state)) {
  260.     XDrawSegments(graphPtr->display, Tk_WindowId(graphPtr->tkwin),
  261.         hairsPtr->gc, hairsPtr->segArr, 2);
  262.     }
  263. }
  264.  
  265. /*
  266.  *----------------------------------------------------------------------
  267.  *
  268.  * UpdateCrosshairs --
  269.  *
  270.  *    Update the length of the hairs (not the hot spot).
  271.  *
  272.  * Results:
  273.  *    None.
  274.  *
  275.  *----------------------------------------------------------------------
  276.  */
  277. static void
  278. UpdateCrosshairs(graphPtr)
  279.     Graph *graphPtr;
  280. {
  281.     Crosshairs *hairsPtr = (Crosshairs *)graphPtr->crosshairs;
  282.  
  283.     hairsPtr->segArr[0].y1 = graphPtr->origin.y;
  284.     hairsPtr->segArr[0].y2 = graphPtr->extreme.y;
  285.     hairsPtr->segArr[1].x1 = graphPtr->origin.x;
  286.     hairsPtr->segArr[1].x2 = graphPtr->extreme.x;
  287. }
  288.  
  289. /*
  290.  *----------------------------------------------------------------------
  291.  *
  292.  * DestroyCrosshairs --
  293.  *
  294.  * Results:
  295.  *    None
  296.  *
  297.  * Side Effects:
  298.  *    Crosshair GC is allocated.
  299.  *
  300.  *----------------------------------------------------------------------
  301.  */
  302. static void
  303. DestroyCrosshairs(graphPtr)
  304.     Graph *graphPtr;
  305. {
  306.     Crosshairs *hairsPtr = (Crosshairs *)graphPtr->crosshairs;
  307.  
  308.     Tk_FreeOptions(configSpecs, (char *)hairsPtr, graphPtr->display, 0);
  309.     if (hairsPtr->gc != NULL) {
  310.     Tk_FreeGC(graphPtr->display, hairsPtr->gc);
  311.     }
  312.     free((char *)hairsPtr);
  313. }
  314.  
  315. /*
  316.  *----------------------------------------------------------------------
  317.  *
  318.  * Blt_CreateCrosshairs --
  319.  *
  320.  *    Creates and initializes a new crosshair structure.
  321.  *
  322.  * Results:
  323.  *    Returns TCL_ERROR if the crosshair structure cannot be created,
  324.  *    otherwise TCL_OK.
  325.  *
  326.  * Side Effects:
  327.  *    Crosshair GC is allocated.
  328.  *
  329.  *----------------------------------------------------------------------
  330.  */
  331. int
  332. Blt_CreateCrosshairs(graphPtr)
  333.     Graph *graphPtr;
  334. {
  335.     Crosshairs *hairsPtr;
  336.  
  337.     hairsPtr = (Crosshairs *)calloc(1, sizeof(Crosshairs));
  338.     if (hairsPtr == NULL) {
  339.     graphPtr->interp->result = "can't allocate crosshairs structure";
  340.     return TCL_ERROR;
  341.     }
  342.     hairsPtr->mapped = hairsPtr->state = 0;
  343.     hairsPtr->anchorPos.x = hairsPtr->anchorPos.y = DEF_POSITION;
  344.     hairsPtr->destroyProc = DestroyCrosshairs;
  345.     hairsPtr->toggleProc = ToggleCrosshairs;
  346.     hairsPtr->updateProc = UpdateCrosshairs;
  347.     hairsPtr->configProc = ConfigureCrosshairs;
  348.     graphPtr->crosshairs = (GraphCrosshairs *)hairsPtr;
  349.     if (Tk_ConfigureWidget(graphPtr->interp, graphPtr->tkwin, configSpecs,
  350.         0, (char **)NULL, (char *)hairsPtr, 0) != TCL_OK) {
  351.     return TCL_ERROR;
  352.     }
  353.     return TCL_OK;
  354. }
  355.  
  356. /*
  357.  *----------------------------------------------------------------------
  358.  *
  359.  * Blt_CrosshairsCmd --
  360.  *
  361.  *    User routine to configure crosshair simulation.  Crosshairs
  362.  *    are simulated by drawing line segments parallel to both axes
  363.  *    using the XOR drawing function. The allows the lines to be
  364.  *    erased (by drawing them again) without redrawing the entire
  365.  *    graph.  Care must be taken to erase crosshairs before redrawing
  366.  *    the graph and redraw them after the graph is redraw.
  367.  *
  368.  * Results:
  369.  *    The return value is a standard Tcl result.
  370.  *
  371.  * Side Effects:
  372.  *    Crosshairs may be drawn in the plotting area.
  373.  *
  374.  *----------------------------------------------------------------------
  375.  */
  376. /* ARGSUSED */
  377. int
  378. Blt_CrosshairsCmd(graphPtr, argc, argv)
  379.     Graph *graphPtr;
  380.     int argc;
  381.     char **argv;
  382. {
  383.     char c;
  384.     int length;
  385.     int boolean;
  386.     Tcl_Interp *interp = graphPtr->interp;
  387.     Crosshairs *hairsPtr = (Crosshairs *)graphPtr->crosshairs;
  388.  
  389.     if (argc < 3) {
  390.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  391.         " crosshairs option ?args?\"", NULL);
  392.     return TCL_ERROR;
  393.     }
  394.     c = argv[2][0];
  395.     length = strlen(argv[2]);
  396.  
  397.     if ((c == 'c') && (strncmp(argv[2], "configure", length) == 0)) {
  398.     if (argc < 3) {
  399.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  400.         " crosshairs configure \"", NULL);
  401.         return TCL_ERROR;
  402.     }
  403.     if (argc == 3) {
  404.         return (Tk_ConfigureInfo(interp, graphPtr->tkwin, configSpecs,
  405.             (char *)hairsPtr, (char *)NULL, 0));
  406.     } else if (argc == 4) {
  407.         return (Tk_ConfigureInfo(interp, graphPtr->tkwin, configSpecs,
  408.             (char *)hairsPtr, argv[3], 0));
  409.     }
  410.     if (Tk_ConfigureWidget(interp, graphPtr->tkwin, configSpecs, argc - 3,
  411.         argv + 3, (char *)hairsPtr, TK_CONFIG_ARGV_ONLY) != TCL_OK) {
  412.         return TCL_ERROR;
  413.     }
  414.     ConfigureCrosshairs(graphPtr);
  415.     return TCL_OK;
  416.     } else if ((c == 't') && (strncmp(argv[2], "toggle", length) == 0)) {
  417.     if (argc != 3) {
  418.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  419.         " crosshairs toggle\"", NULL);
  420.         return TCL_ERROR;
  421.     }
  422.     boolean = (!hairsPtr->mapped);
  423.     } else if ((c == 's') && (strncmp(argv[2], "set", length) == 0)) {
  424.     if (argc != 4) {
  425.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  426.         " crosshairs set boolean\"", NULL);
  427.         return TCL_ERROR;
  428.     }
  429.     if (Tcl_GetBoolean(graphPtr->interp, argv[3], &boolean) != TCL_OK) {
  430.         return TCL_ERROR;
  431.     }
  432.     } else {
  433.     Tcl_AppendResult(interp, "bad crosshairs option \"", argv[2],
  434.         "\": should be configure, set, or toggle", (char *)NULL);
  435.     return TCL_ERROR;
  436.     }
  437.     if (hairsPtr->mapped == boolean) {
  438.     return TCL_OK;
  439.     }
  440.     hairsPtr->mapped = boolean;
  441.  
  442.     if (hairsPtr->mapped) {
  443.     TurnOnHairs(graphPtr->tkwin, hairsPtr);
  444.     } else {
  445.     TurnOffHairs(graphPtr->tkwin, hairsPtr);
  446.     }
  447.     return TCL_OK;
  448. }
  449.